package com.example.mqttclient.mqtt;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
// MqttService类是一个Android服务，用于管理MQTT连接、订阅、发布等操作
public class MqttService extends Service {
    // 用于日志记录的标签
    public static final String TAG = MqttService.class.getSimpleName();
    // MQTT客户端实例
    private static MqttAndroidClient client;
    // MQTT事件回调接口实例
    private MqttEventCallBack mqttEventCallBack;
    // 用于绑定服务的Binder实例
    private MqttBinder mqttBinder = new MqttBinder();
    // MQTT连接选项
    MqttConnectOptions conOpt = new MqttConnectOptions();

    // 服务创建时调用，用于初始化操作
    @Override
    public void onCreate() {
        super.onCreate();
        // 读取配置并连接MQTT服务器
        connect(MqttParametersManager.readConfig(this));
    }

    // 定义MQTT事件回调接口
    public interface MqttEventCallBack {
        // 连接成功时的回调方法
        void onConnectSuccess();
        // 连接失败时的回调方法，参数为错误信息
        void onConnectError(String error);
        // 消息发布完成时的回调方法
        void onDeliveryComplete();
        // 接收到MQTT消息时的回调方法，参数为主题和消息内容
        void onMqttMessage(String topic, String message);
    }

    // 当其他组件绑定到服务时调用，返回用于通信的Binder
    @Override
    public IBinder onBind(Intent intent) {
        return mqttBinder;
    }

    // MqttBinder类，用于在服务和绑定组件之间进行通信
    public class MqttBinder extends Binder {
        // 重新连接MQTT服务器的方法，在新线程中执行
        public void reConnect() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    connect(MqttParametersManager.readConfig(MqttService.this));
                }
            }).start();
        }

        // 判断MQTT客户端是否已连接
        public boolean isConnected() {
            return client != null && client.isConnected();
        }

        // 订阅指定主题的方法，若客户端已连接则执行订阅操作
        public void subscribe(String topic) throws MqttException {
            if (client != null && client.isConnected()) {
                client.subscribe(topic, 1);
            }
        }

        // 取消订阅指定主题的方法，若客户端已连接则执行取消订阅操作
        public void unSubscribe(String topic) throws MqttException {
            if (client != null && client.isConnected()) {
                client.unsubscribe(topic);
            }
        }

        // 发布消息的方法，若客户端已连接则执行发布操作
        public void publishMessage(String topic, String message) throws MqttException {
            if (client != null && client.isConnected()) {
                client.publish(topic, message.getBytes(), 0, false);
            }
        }

        // 设置MQTT事件回调接口实例
        public void setMqttEventCallback(MqttEventCallBack callback) {
            mqttEventCallBack = callback;
        }
    }

    // 连接MQTT服务器的方法
    private void connect(MqttParameters parameters) {
        // 断开当前连接（如果已连接）
        disConnect();
        // 创建MQTT客户端实例
        client = new MqttAndroidClient(this, parameters.getUri(), parameters.clientId);
        // 设置MQTT回调，用于接收消息、处理连接丢失等事件
        client.setCallback(mqttCallback);
        // 设置清除会话标志，每次连接时清除缓存
        conOpt.setCleanSession(true);
        // 设置连接超时时间为10秒
        conOpt.setConnectionTimeout(10);
        // 设置心跳包发送间隔为20秒
        conOpt.setKeepAliveInterval(20);
        // 如果设置了用户名和密码，则进行设置
        if ((parameters.userName != null) && (!parameters.userName.trim().equals(""))
                && (parameters.passWord != null) && (!parameters.passWord.trim().equals(""))) {
            conOpt.setUserName(parameters.userName);
            conOpt.setPassword(parameters.passWord.toCharArray());
        }
        // 设置遗嘱消息，当客户端意外断开时发送
        String lwtMessage = "{\"terminal_uid\":\"" + parameters.clientId + "\"}";
        try {
            conOpt.setWill(parameters.clientId, lwtMessage.getBytes(), 0, false);
        } catch (Exception e) {
            // 若设置遗嘱消息失败，调用连接失败的回调
            iMqttActionListener.onFailure(null, e);
        }
        // 尝试连接MQTT服务器
        try {
            if (!client.isConnected()) {
                client.connect(conOpt, null, iMqttActionListener);
            }
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    // 断开MQTT连接的方法
    private void disConnect() {
        // 如果客户端已连接，则断开连接
        if (client != null && client.isConnected()) {
            try {
                client.disconnect();
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }

    // 服务销毁时调用，用于清理资源
    @Override
    public void onDestroy() {
        // 停止服务自身
        stopSelf();
        // 断开MQTT连接
        disConnect();
        super.onDestroy();
    }

    // MQTT连接操作的监听器
    private IMqttActionListener iMqttActionListener = new IMqttActionListener() {
        // 连接成功时的回调方法
        @Override
        public void onSuccess(IMqttToken arg0) {
            Log.i(TAG, "connect success");
            // 如果设置了回调接口，则调用连接成功的回调
            if (mqttEventCallBack != null) {
                mqttEventCallBack.onConnectSuccess();
            }
        }

        // 连接失败时的回调方法
        @Override
        public void onFailure(IMqttToken arg0, Throwable arg1) {
            Log.i(TAG, "connect fail:" + arg1.toString());
            // 如果设置了回调接口，则调用连接失败的回调
            if (mqttEventCallBack != null) {
                mqttEventCallBack.onConnectError(arg1.toString());
            }
            // 调用连接丢失的回调方法
            mqttCallback.connectionLost(arg1);
        }
    };

    // MQTT回调接口实现，用于处理消息接收、发布完成、连接丢失等事件
    private MqttCallback mqttCallback = new MqttCallback() {
        // 接收到MQTT消息时的回调方法
        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {
            // 将消息内容转换为字符串
            String str1 = new String(message.getPayload());
            // 如果设置了回调接口，则调用消息接收的回调
            if (mqttEventCallBack != null) {
                mqttEventCallBack.onMqttMessage(topic, str1);
            }
            Log.i(TAG, "messageArrived:" + str1);
        }

        // 消息发布完成时的回调方法
        @Override
        public void deliveryComplete(IMqttDeliveryToken arg0) {
            // 如果设置了回调接口，则调用消息发布完成的回调
            if (mqttEventCallBack != null) {
                mqttEventCallBack.onDeliveryComplete();
            }
        }

        // 连接丢失时的回调方法
        @Override
        public void connectionLost(Throwable arg0) {
            // 如果设置了回调接口，则调用连接丢失的回调
            if (mqttEventCallBack != null) {
                mqttEventCallBack.onConnectError("Connecting lost! MqttService will reconnect after 5s...");
            }
            try {
                // 等待5秒后尝试重新连接
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 如果客户端未连接，则尝试重新连接
            if (client != null &&!client.isConnected()) {
                try {
                    client.connect(conOpt, null, iMqttActionListener);
                } catch (MqttException e) {
                    e.printStackTrace();
                }
            }
        }
    };
}